package fun.codedesign.principle.advice151.a127;

import org.junit.Test;

import java.util.Calendar;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 对象锁和类锁 <br>
 * <pre>
 *     sync可以锁对象也可以锁类
 *     lock一般是跟着对象走的
 * </pre>
 *
 * @author zengjian
 * @create 2018-07-09 20:47
 * @since 1.0.0
 */
public class LockAndSync {
    public static void executeTask2(Class<? extends Runnable> clz) throws Exception {
        ExecutorService pool = Executors.newCachedThreadPool();
        System.out.println("线程开始" + clz.getSimpleName());
        for (int i = 0; i < 3; i++) {
            pool.submit(clz.newInstance());

        }
        TimeUnit.SECONDS.sleep(10);
        System.out.println("任务结束" + clz.getName() + "\n");
        pool.shutdown();
    }

    // 建议127： Lock与synchronized是不一样的,lock锁对象
    // lock锁定的是对象， synchronized锁定的类
    @Test
    public void test127() throws Exception {
        executeTask2(LockTask1.class);
        executeTask2(SyncTask2.class);
    }
}


class SyncTask2 extends Task implements Runnable {

    @Override
    public void run() {
        try {
            synchronized ("A") {
                doSomething();
            }
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }
}

class LockTask1 extends Task implements Runnable {

    private final Lock lock = new ReentrantLock();

    @Override
    public void run() {
        try {
            lock.lock();
            doSomething();
        } finally {
            lock.unlock();
        }
    }
}

class Task {
    public void doSomething() {
        try {
            Thread.sleep(3000);
        } catch (Exception e) {
            System.out.println("111");
        }
        StringBuffer sb = new StringBuffer();
        sb.append("线程名称" + Thread.currentThread().getName()).append(
                "当前时间秒数" + Calendar.getInstance().get(Calendar.SECOND));
        System.out.println(sb);
    }
}
